package proyecto;

import java.util.ArrayList;

import json.JsonObject;
import es.upv.dsic.gti_ia.core.ACLMessage;

import java.io.File;
import java.io.IOException;

//import biblioteca grafica;

import es.upv.dsic.gti_ia.core.AgentID;
import es.upv.dsic.gti_ia.core.SingleAgent;

public class Satelite extends SingleAgent {
    private final int Peticion_de_informacion = 0, RESPUESTA = 1;
    private int status;
    private mapa mapa;
    private ACLMessage inbox, outbox;
    private boolean encontrado;
    ArrayList<Pair> meta = new ArrayList<Pair>(); //Casilla donde estara la meta
    private int cizq, cder, caba, carr, cane, casw, ca_se, canw; //Valor de las casillas donde se puede mover el drone
    private int fild, cold; //Posision del drone
    private int dist;
    private double angl;
    
    Start m;
    
    private JsonObject obj=new JsonObject();
    String informacion,ruta;
    
    /** Paint the way in an image **/
    private printWay image;
    
    /** Map name **/
    private String mapName;
    
    private File f;
    
    /** droneWay **/
    private ArrayList<Pair> way;
    
    private int h=0;
    
    
    public Satelite( AgentID aid) throws Exception  {
        super(aid);
    }
    
    public Satelite(mapa map, AgentID aid,Start ma,String rut) throws Exception  {
        super(aid);
        mapa=map;
        m=ma;
        ruta=rut;
    }
    
    
    public void init()  {
        System.out.println("Satelite("+this.getName()+") Iniciando");
        status = Peticion_de_informacion;
        inbox = null;
        outbox = null;
        encontrado = false;

      //  mapName = "imagenes/map4.png";
        mapName =ruta;
        f =new File (mapName);
        mapa = new mapa(f);

        way = new ArrayList<Pair>();
    }
        
    public void execute(){
        System.out.println("Satelite("+this.getName()+") Ejecución");
        meta=mapa.solution();
        while (!encontrado)  {
            switch(status)  {
                case Peticion_de_informacion:
                	try {
                        inbox = receiveACLMessage();
                        
	                } catch (InterruptedException ex) {
	                	System.err.println("Satelite("+this.getName()+") Error de comunicación");
	                 	encontrado = true;
	              	}
                	
                    if (inbox.getPerformative().equals("REQUEST")) {
                        status = RESPUESTA;
                        //System.out.println(" LOCOO ");
                    }
                    if (inbox.getPerformative().equals("FAILURE")){
                    	
                    	outbox = new ACLMessage();
                        outbox.setSender(this.getAid());
                        outbox.addReceiver(inbox.getSender());
                        outbox.setPerformative(ACLMessage.AGREE);
                        this.send(outbox);
                        encontrado=true;
                    }
                    else{
                    	if (inbox.getPerformative().equals("CONFIRM")) {
              
                    	//System.out.println(" LOCOO CONFIRM0 ");
                    	
                    	try {
							image = new printWay( way, f, mapName);
						} catch (IOException e) {
							e.printStackTrace();
						}
                        encontrado=true;
                        //System.out.println(" LOCOO CONFIRM ");
                    	}
	                    else{
	                    	//recibe informacion del drone con su posicion 
	                        informacion= inbox.getContent();
	
	                        obj= JsonObject.readFrom( informacion );
	                         
	                        fild= obj.get( "posx" ).asInt();
	                        cold= obj.get( "posy" ).asInt();
	                        
	                        //Las guardamos al revés porque png trabaja al revés
	                        way.add(new Pair(cold,fild));
	                        
	                        System.out.println(" El dron dice que está en " + fild + " " + cold);
	                        ++h;
	                        if ( h%10 == 0){
	                        	 try {
	 								image = new printWay( way, f, mapName);
	 							} catch (IOException e) {
	 								// TODO Auto-generated catch block
	 								e.printStackTrace();
	 							}
	                        }
	                       
	                    }
                    }              
                    
                    break;
                    
                case RESPUESTA:
                	//System.out.println("Inicio de RESPUESTA en Satelite");
                    outbox = new ACLMessage();
                    //System.out.println("Inicio1 de RESPUESTA en Satelite");
                    outbox.setSender(this.getAid());
                    //System.out.println("Inicio2 de RESPUESTA en Satelite");
                    outbox.addReceiver(inbox.getSender());
                    //System.out.println("Inicio3 de RESPUESTA en Satelite");
                    
                    //System.out.println("meta.get(0).getFirst() = " +meta.get(0).getFirst());
                    //System.out.println("meta.get(0).getSecond() = "+meta.get(0).getSecond());
                    
                    if ( meta.get(0).getFirst() == fild && meta.get(0).getSecond() == cold ){
                    	outbox.setPerformative(ACLMessage.AGREE);
                    	//System.out.println("Satelite envia AGREE");
                    }
                    else{
                    	outbox.setPerformative(ACLMessage.REFUSE);
                    	carr=mapa.getContent(fild-1,cold);
                        //System.out.println("carr = "+carr);
                        
                        cane=mapa.getContent(fild-1,cold+1);
                        //System.out.println("cane = "+cane);
                        
                        cder=mapa.getContent(fild,cold+1);
                        //System.out.println("cder = "+cder);
                        
                        ca_se=mapa.getContent(fild+1,cold+1);
                        //System.out.println("ca_se = "+ca_se);
                        
                        caba=mapa.getContent(fild+1,cold);
                        //System.out.println("caba = "+caba);
                        
                        casw=mapa.getContent(fild+1,cold-1);
                        //System.out.println("casw = "+casw);
                        
                        cizq=mapa.getContent(fild,cold-1);
                        //System.out.println("cizq = "+cizq);
                                   
                        canw=mapa.getContent(fild-1,cold-1);
                        //System.out.println("canw = "+canw);
                        
                        dist=calcularDist(meta,fild,cold);
                        angl=calcularAng(meta,fild,cold);
                        //System.out.println("Angulo en Satelite = "+angl);
                             
                        //System.out.println("Antes de JsonObject obj2= new JsonObject().add( angl,angl).add( dist,dist).add en Satelite");
                        //envia al droide informacion de las casillas de alrededor, distancia al objetivo
                        JsonObject obj2= new JsonObject().add( "angl",angl).add( "dist",dist).add( "casi_nort",carr).add( "casi_ne" , cane ).add( "cas_est",cder).add( "casi_se", ca_se ).add( "cas_sur",caba).add ( "ca_sw" , casw).add( "cas_oest",cizq).add( "ca_nw" , canw);
                        informacion=obj2.toString();
                        
                        outbox.setContent(informacion); 
                    }
                                       
                    this.send(outbox);
                    status = Peticion_de_informacion;
                    
                    //System.out.println("Final de RESPUESTA en Satelite");
                    break;
            }
        }
    }
    
    public int calcularDist(ArrayList<Pair> meta, int fil, int col){
    	int distancia, a, b;
    	
    	a=Math.abs(fil-meta.get(0).getFirst());
    	b=Math.abs(col-meta.get(0).getSecond());
    	distancia=(int)Math.sqrt(a*a+b*b);   	
    	
    	return distancia;
    }
    
    public double calcularAng(ArrayList<Pair> meta, int fil, int col){
    	double angulo, a, b, c;
    	int filb=meta.get(0).getFirst(), colb=meta.get(0).getSecond();
    	
    	a=Math.abs(fil-filb);
    	//System.out.println("a = "+a);
    	b=Math.abs(col-colb);
    	//System.out.println("b = "+b);
    	c= Math.sqrt(a*a+b*b);
    	//System.out.println("C = "+c);
    	//System.out.println("asin(a/c) = "+Math.asin(a/c) );
    	angulo=(double)Math.asin(a/c);
    	angulo=(angulo*180)/Math.PI;
    	
    	if(fil-filb>0 && col-colb<=0){
    		angulo=360-angulo;
    	}
    	else if(fil-filb>0 && col-colb>0){
    		angulo=270-angulo;
    	}
    	else if(fil-filb<=0 && col-colb>0){
    		angulo=180-angulo;
    	}
    	
    	//System.out.println("Angulo en Satelite en calcularAng = "+angulo);
    	return angulo;
    }
    
    public void finalize()  {
    	mapa.satelitefin();
    	m.fin=true;
        System.out.println("Satelite("+this.getName()+") Terminando");
        
    }
}